package com.model.math;

import com.model.math.Point3D;

public class Matrix3D {
    private static final boolean DEBUG = true;
    
    private void debugPrint(String message) {
        if (DEBUG) {
            System.out.println("[Matrix3D] " + message);
        }
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 3; i++) {
            sb.append(String.format("[%.2f, %.2f, %.2f]\n", 
                data[i][0], data[i][1], data[i][2]));
        }
        return sb.toString();
    }

    private double[][] data;

    public Matrix3D() {
        data = new double[3][3];
    }

    // 计算协方差矩阵
    public static Matrix3D computeCovarianceMatrix(Point3D[] points) {
        Matrix3D matrix = new Matrix3D();
        if (points.length == 0) return matrix;

        // 计算中心点
        Point3D center = Point3D.computeCenter(points);

        // 计算协方差矩阵
        for (Point3D point : points) {
            double dx = point.x - center.x;
            double dy = point.y - center.y;
            double dz = point.z - center.z;

            matrix.data[0][0] += dx * dx;
            matrix.data[0][1] += dx * dy;
            matrix.data[0][2] += dx * dz;
            matrix.data[1][1] += dy * dy;
            matrix.data[1][2] += dy * dz;
            matrix.data[2][2] += dz * dz;
        }

        matrix.data[1][0] = matrix.data[0][1];
        matrix.data[2][0] = matrix.data[0][2];
        matrix.data[2][1] = matrix.data[1][2];

        // 归一化
        int n = points.length;
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                matrix.data[i][j] /= n;
            }
        }

        return matrix;
    }

    // 计算特征向量（使用幂迭代法）
    public Vector3D[] computeEigenVectors() {
        debugPrint("开始计算特征向量");
        Vector3D[] eigenVectors = new Vector3D[3];
        
        // 使用幂迭代法计算主特征向量
        debugPrint("计算第一个特征向量");
        eigenVectors[0] = powerIteration(100);
        debugPrint("第一个特征向量: " + eigenVectors[0]);
        
        // 计算第二个特征向量
        debugPrint("计算第二个特征向量");
        Vector3D v2 = eigenVectors[0].getPerpendicularVector();
        eigenVectors[1] = v2.normalize();
        debugPrint("第二个特征向量: " + eigenVectors[1]);
        
        // 计算第三个特征向量
        debugPrint("计算第三个特征向量");
        eigenVectors[2] = eigenVectors[0].cross(eigenVectors[1]);
        debugPrint("第三个特征向量: " + eigenVectors[2]);
        
        return eigenVectors;
    }

    private Vector3D powerIteration(int iterations) {
        Vector3D v = new Vector3D(1, 0, 0);
        for (int i = 0; i < iterations; i++) {
            v = multiply(v).normalize();
        }
        return v;
    }

    private Vector3D multiply(Vector3D v) {
        double x = data[0][0] * v.x + data[0][1] * v.y + data[0][2] * v.z;
        double y = data[1][0] * v.x + data[1][1] * v.y + data[1][2] * v.z;
        double z = data[2][0] * v.x + data[2][1] * v.y + data[2][2] * v.z;
        return new Vector3D(x, y, z);
    }
} 